home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1997 August / Walnut Creek CDROM.7z / VOL_400 / 460_01 / YACL0160.ZIP / uidemo / calc / appwin.cxx next >
Encoding:
C/C++ Source or Header  |  1996-02-29  |  5.8 KB  |  214 lines

  1.  
  2. #include "appwin.h"
  3. #include "ui/label.h"
  4. #include "ui/point.h"
  5. #include "ui/xrbtngrp.h"
  6. #include "ui/toglbtn.h"
  7. #include "ui/containr.h"
  8. #include "ui/pushbtn.h"
  9. #include "ui/xrtglbtn.h"
  10. #include "ui/cntroler.h"
  11.  
  12. enum {
  13.     ID_CLEAR       = 23,   // View id of  the "Clear" button
  14.     ID_RADIX       = 30,   // View id of the radix selection box
  15.     ID_DIGITS_BASE = 1,    // First view id used by digits buttons
  16.     ID_OPS_BASE    = 100   // First view id used by operations buttons
  17. };
  18.  
  19. const char* ops[] = {
  20.     "+", "-", "*", "/", "%",
  21. #if defined(__MS_WINDOWS__)
  22.     "&&",
  23. #else
  24.     "&",
  25. #endif        
  26.     "|", ">>", "<<", "=", 0};
  27.  
  28. const char digits[] = "0123456789ABCDEF";
  29.  
  30. AppWindow::AppWindow ()
  31. : UI_Dialog (NULL, NULL, UI_Rectangle (50, 50, 400, 300))
  32. {
  33.     Title() = "YACL Calculator";
  34.     _op = '=';
  35.     _top = 0;
  36.     _stack[0] = 0;
  37.     _stack[1] = 0;
  38.  
  39.     // Create the label
  40.     _label = new UI_Label (this, UI_Rectangle (20, 5, 150, 25));
  41.     _label->Title() = "0";
  42.     _label->ShowBorder ();
  43.     _label->SetTextStyle (UIText_Right);
  44.  
  45.     // Create the "Clear" button
  46.     UI_PushButton*  btn = new UI_PushButton
  47.         (this, UI_Rectangle (30, 200, 60, 30), ID_CLEAR);
  48.     btn->Title() = "Clear";
  49.  
  50.     UI_Rectangle result      (40,    5, 150,  25);
  51.     UI_Rectangle digitsPanel (10,   40, 140, 140);
  52.     UI_Rectangle opsPanel    (160,  40, 175,  70);
  53.     UI_Rectangle radixRect   (160, 110, 220, 180);
  54.     
  55.     MakeDigitButtons (digitsPanel);    // Create the digit buttons
  56.     MakeOpButtons    (opsPanel);       // Create the operations buttons
  57.     MakeRadixPanel   (radixRect);      // Create the radix panel
  58.     
  59.     DoRadix (10);                      // Initial radix is decimal
  60. }
  61.  
  62.  
  63. void AppWindow::MakeDigitButtons (const UI_Rectangle& panel)
  64. {
  65.     UI_PushButton* btn;
  66.     UI_PointSequence seq = panel.RowMajor (35, 35);
  67.     short n = seq.Size();
  68.     for (short i = 0; i < n; i++) {
  69.         UI_Rectangle shape (seq[i], 25, 25);
  70.         btn = new UI_PushButton (this, shape, i + ID_DIGITS_BASE);
  71.         btn->Title() = CL_String (digits[i], 1);
  72.     }
  73. }
  74.  
  75.  
  76. void AppWindow::MakeOpButtons (const UI_Rectangle& panel)
  77. {
  78.     UI_PushButton* btn;
  79.     UI_PointSequence seq = panel.RowMajor (35, 35);
  80.     for (short i = 0; ops[i] != 0; i++) {
  81.         btn = new UI_PushButton (this, UI_Rectangle (seq[i], 25, 25),
  82.              (UI_ViewID) (ID_OPS_BASE + ops[i][0])); // Map id's to operations
  83.         btn->Title() = ops[i];
  84.     }
  85. }
  86.  
  87.  
  88. void AppWindow::MakeRadixPanel (const UI_Rectangle& panel)
  89. {
  90.     UI_ExOrButtonGroup* grp = new UI_ExOrButtonGroup (this, panel, ID_RADIX);
  91.     grp->Title() = "Radix";
  92.     UI_ExOrToggleButton* xor_btn;
  93.     UI_PointSequence seq = UI_Rectangle (15, 25, 210, 140).RowMajor (50, 30);
  94.     for (short i = 2; i <= 16; i++) {
  95.         UI_Rectangle shape (seq[i-2], 45, 25);
  96.         xor_btn = new UI_ExOrToggleButton (grp, shape, i + ID_RADIX);
  97.         xor_btn->Title() = CL_String (i);
  98.     }
  99.     grp->Selection() = ID_RADIX + 10; // Decimal
  100. }
  101.  
  102.  
  103. bool AppWindow::HandleChildEvent (const UI_Event& e)
  104. {
  105.     UI_Dialog::HandleChildEvent (e);
  106.     if (e.Type() == Event_KeyTyped) {
  107.         short key = e.Key();
  108.         bool b = (key >= '0' && key < _radix + '0') 
  109.           ?  DoDigit (key - '0')
  110.           :  DoOp (key);
  111. //         if (!b)
  112. //             _Controller->Beep();
  113.         return TRUE;
  114.     }
  115.     if (e.Type() != Event_Select)
  116.         return FALSE;
  117.     UI_VisualObject& origin = *(e.Origin());
  118.     UI_ViewID id = origin.ViewID();
  119.     if (id == ID_RADIX) { // User changed the current radix
  120.         short radix = ((UI_ExOrButtonGroup*) (*this)[ID_RADIX])
  121.             ->Selection() - ID_RADIX;
  122.         DoRadix (radix);
  123.     }
  124.     else if (id == ID_CLEAR) { // User clicked the Clear button
  125.         DoClear();
  126.         return TRUE;
  127.     }
  128.     else if (id >= ID_DIGITS_BASE && id < ID_DIGITS_BASE + 16)
  129.         // User clicked on a digit button
  130.         DoDigit (id - ID_DIGITS_BASE);
  131.     else  // User clicked on an operation button
  132.         DoOp (id - ID_OPS_BASE);
  133.     return TRUE;
  134. }
  135.  
  136.  
  137. void AppWindow::DoRadix (short radix)
  138. {
  139.     _radix = radix;
  140.     _label->Title() = CL_Integer(_stack[_top]).InRadix (_radix);
  141.     // Enable the appropriate buttons
  142.     short i;
  143.     for (i = 0; i < _radix; i++)
  144.         (*this)[i+ID_DIGITS_BASE]->Enable();
  145.     for (i = _radix; i < 16; i++)
  146.         (*this)[i+ID_DIGITS_BASE]->Disable();
  147. }
  148.  
  149.  
  150. void AppWindow::DoClear ()
  151. {
  152.     _top = 0;
  153.     _stack[0] = 0;
  154.     _label->Title() = "0";
  155. }
  156.  
  157. bool AppWindow::DoDigit (short digit)
  158. {
  159.     _stack[_top] = _stack[_top] * _radix + digit;
  160.     _label->Title() = CL_Integer(_stack[_top]).InRadix (_radix);
  161.     return TRUE;
  162. }
  163.  
  164.  
  165. bool AppWindow::DoOp (char op)
  166. {
  167.     if (op != '+' && op != '-' && op != '*' && op != '/' && op != '%'
  168.         && op != '<' && op != '>' && op != '&' && op != '|' && op != '=')
  169.         return FALSE;
  170.     if (op != '=' && _top == 0) {
  171.         _top = 1;
  172.         _op = op;
  173.         _stack[_top] = 0;
  174.         _label->Title() = "0";
  175.         return TRUE;
  176.     }
  177.     switch (_op) {
  178.     case '+': _stack[_top-1] += _stack[_top]; break;
  179.         
  180.     case '-': _stack[_top-1] -= _stack[_top]; break;
  181.         
  182.     case '*': _stack[_top-1] *= _stack[_top]; break;
  183.         
  184.     case '/': _stack[_top-1] /= _stack[_top]; break;
  185.         
  186.     case '%': _stack[_top-1] %= _stack[_top]; break;
  187.         
  188.     case '&': _stack[_top-1] &= _stack[_top]; break;
  189.         
  190.     case '|': _stack[_top-1] |= _stack[_top]; break;
  191.         
  192.     case '>': _stack[_top-1] >>= _stack[_top]; break;
  193.         
  194.     case '<': _stack[_top-1] <<= _stack[_top]; break;
  195.         
  196.     case '=': if (_top == 1)
  197.                   _stack[_top-1] = _stack[_top--];
  198.               break;
  199.  
  200.     default: return FALSE;
  201.     };
  202.  
  203.     if (op == '=') {
  204.         _top = 0;
  205.     }
  206.     else {
  207.         _top = 1;
  208.         _stack[_top] = 0;
  209.     }
  210.     _op = op;
  211.     _label->Title() = CL_Integer (_stack[0]).InRadix (_radix);
  212.     return TRUE;
  213. }
  214.